package ink.tsg.geo.utils;
import com.alibaba.fastjson.support.geo.MultiLineString;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.MultiPolygon;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import com.vividsolutions.jts.io.ParseException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.geometry.aggregate.MultiPoint;
import org.opengis.geometry.coordinate.LineString;
import org.opengis.geometry.coordinate.Polygon;
import org.opengis.geometry.primitive.Point;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author geo_tsg
 * @version 1.0.0
 * @ClassName ShapeFileUtils.java
 * @Description shape文件的操作
 * @createTime 2021-07-29
 */
public class ShapeFileUtils {

    private static final String GEOM_KEY = "the_geom";
    private static final String PLOT_TYPE = "Coordinate"; //数据库里面用来表示坐标的属性

//    public ArrayList<ShapeModel> readShapeFile(String filePath) {
//        ArrayList<ShapeModel> modelList = new ArrayList<>();
//        File folder = new File(filePath);
//        if (!folder.isDirectory()) {
//            if (folder.toString().endsWith(".shp")) {
//                try {
//                    modelList = getShapeFile(folder);
//                    return modelList;
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            } else {
//                System.out.println("选择的文件后缀名不是.shp");
//            }
//        }else{
//            File[] files = folder.listFiles();
//            if (!(files.length > 0)) {
//                System.out.println("目录文件为空");
//                return modelList;
//            }
//
//            for (File file : files) {
//                if (!file.toString().endsWith(".shp")) {
//                    continue;
//                }
//                try {
//                    ArrayList<ShapeModel> models = getShapeFile(file);
//                    modelList.addAll(models);
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//        return modelList;
//    }
//
//    private ArrayList<ShapeModel> getShapeFile(File file) throws Exception {
//
//        Map<String, Object> map = new HashMap<String, Object>();
//        map.put("url", file.toURI().toURL());
//        ArrayList<ShapeModel> models = new ArrayList<>();
//        DataStore dataStore = DataStoreFinder.getDataStore(map);
//        //字符转码，防止中文乱码
//        ((ShapefileDataStore) dataStore).setCharset(Charset.forName("utf8"));
//        String typeName = dataStore.getTypeNames()[0];
//        FeatureSource<SimpleFeatureType, SimpleFeature> source = dataStore.getFeatureSource(typeName);
//        FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures();
//        FeatureIterator<SimpleFeature> features = collection.features();
//        while (features.hasNext()) {
//            SimpleFeature feature = features.next();
//            ShapeModel model = new ShapeModel();
//            Iterator<? extends Property> iterator = feature.getValue().iterator();
//            while (iterator.hasNext()) {
//                Property property = iterator.next();
//                //property数据与实体类对应
//                if (property.getName().toString().equals("the_geom"))
//                    model.setGeoStr(property.getValue().toString());
//                if (property.getName().toString().equals("layer"))
//                    model.setLayer(property.getValue().toString());
//                if (property.getName().toString().equals("projection"))
//                    model.setProjection(property.getValue().toString());
//                if (property.getName().toString().equals("region"))
//                    model.setRegion(property.getValue().toString());
//                if (property.getName().toString().equals("regionCode"))
//                    model.setRegionCode(property.getValue().toString());
//                if (property.getName().toString().equals("level"))
//                    model.setLevel(Integer.parseInt(property.getValue().toString()));
//                if (property.getName().toString().equals("time"))
//                    model.setTime(property.getValue().toString());
//                model.setCreateTime(new Date());
//                model.setClazz("");
//
//            }
//            models.add(model);
//        }
//        return models;
//    }

    /**
     * 生成shape文件
     *
     * @param shpPath 生成shape文件路径（包含文件名称）
     * @param encode  编码
     * @param geoType 图幅类型，Point和Rolygon
     * @param geoms   图幅集合
     */
    public static void write2Shape(String shpPath, String encode, String geoType, List<Geometry> geoms) {
        try {
            //创建shape文件对象
            File file = new File(shpPath);
            Map<String, Serializable> params = new HashMap<>();
            params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
            //定义图形信息和属性信息
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(DefaultGeographicCRS.WGS84);
            tb.setName("shapefile");

            if ("Polygon".equals(geoType)) {
                tb.add("the_geom", Polygon.class);
            } else if ("MultiPolygon".equals(geoType)) {
                tb.add("the_geom", MultiPolygon.class);
            } else if ("Point".equals(geoType)) {
                tb.add("the_geom", Point.class);
            } else if ("MultiPoint".equals(geoType)) {
                tb.add("the_geom", MultiPoint.class);
            } else if ("LineString".equals(geoType)) {
                tb.add("the_geom", LineString.class);
            } else if ("MultiLineString".equals(geoType)) {
                tb.add("the_geom", MultiLineString.class);
            } else {
                throw new Exception("Geometry中没有该类型：" + geoType);
            }

            ds.createSchema(tb.buildFeatureType());
            //设置编码
            Charset charset = Charset.forName(encode);
            ds.setCharset(charset);
            //设置Writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
            for (Geometry geom : geoms) {
                //String type = geom.getGeometryType();

                //写下一条
                SimpleFeature feature = writer.next();

                feature.setAttribute("the_geom", geom);
            }
            writer.write();
            writer.close();
            ds.dispose();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成shape文件
     *
     * @param shpPath  生成shape文件路径（包含文件名称）
     * @param encode   编码
     * @param geoType  图幅类型，Point和Rolygon
     * @param shpKey   data中图幅的key
     * @param attrKeys 属性key集合
     * @param data     图幅和属性集合
     */
    public static void write2Shape(String shpPath, String encode, String geoType, String shpKey, List<String> attrKeys, List<Map<String, Object>> data) {
        try {
            if (data == null || data.size() == 0) {
                return;
            }
            //创建shape文件对象
            File file = new File(shpPath);
            Map<String, Serializable> params = new HashMap<>();
            params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);

            //定义图形信息和属性信息
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(DefaultGeographicCRS.WGS84);
            tb.setName("shapefile");

            if ("Polygon".equals(geoType)) {
                tb.add("the_geom", Polygon.class);
            } else if ("MultiPolygon".equals(geoType)) {
                tb.add("the_geom", MultiPolygon.class);
            } else if ("Point".equals(geoType)) {
                tb.add("the_geom", Point.class);
            } else if ("MultiPoint".equals(geoType)) {
                tb.add("the_geom", MultiPoint.class);
            } else if ("LineString".equals(geoType)) {
                tb.add("the_geom", LineString.class);
            } else if ("MultiLineString".equals(geoType)) {
                tb.add("the_geom", MultiLineString.class);
            } else {
                throw new Exception("Geometry中没有该类型：" + geoType);
            }

            for (String field : attrKeys) {
                tb.add(field.toUpperCase(), String.class);
            }

            ds.createSchema(tb.buildFeatureType());
            //设置编码
            Charset charset = Charset.forName(encode);
            ds.setCharset(charset);
            //设置Writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
            //写入文件信息
            for (int i = 0; i < data.size(); i++) {
                SimpleFeature feature = writer.next();
                Map<String, Object> row = data.get(i);
                Geometry geom = (Geometry) row.get(shpKey);
                feature.setAttribute("the_geom", geom);
                for (String key : row.keySet()) {
                    if (!key.equals(shpKey)) {
                        if (row.get(key) != null) {
                            feature.setAttribute(key.toUpperCase(), row.get(key).toString());
                        } else {
                            feature.setAttribute(key.toUpperCase(), "");
                        }
                    }
                }
            }
            writer.write();
            writer.close();
            ds.dispose();

            //添加到压缩文件
            //zipShapeFile(shpPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 压缩shape文件
     *
     * @param shpPath shape文件路径（包含shape文件名称）
     */
    public static void zipShapeFile(String shpPath) {
        try {
            File shpFile = new File(shpPath);
            String shpRoot = shpFile.getParentFile().getPath();
            String shpName = shpFile.getName().substring(0, shpFile.getName().lastIndexOf("."));

            String zipPath = shpRoot + File.separator + shpName + ".zip";
            File zipFile = new File(zipPath);
            InputStream input = null;
            ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
            // zip的名称为
            zipOut.setComment(shpName);
            String[] shpFiles = new String[]{
                    shpRoot + File.separator + shpName + ".dbf",
                    shpRoot + File.separator + shpName + ".prj",
                    shpRoot + File.separator + shpName + ".shp",
                    shpRoot + File.separator + shpName + ".shx",
                    shpRoot + File.separator + shpName + ".fix"
            };

            for (int i = 0; i < shpFiles.length; i++) {
                File file = new File(shpFiles[i]);
                input = new FileInputStream(file);
                zipOut.putNextEntry(new ZipEntry(file.getName()));
                int temp = 0;
                while ((temp = input.read()) != -1) {
                    zipOut.write(temp);
                }
                input.close();
            }
            zipOut.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws ParseException {
//        String filePath = "E:\\geom\\区划\\省.shp";
//        ShapeFileUtils shapeReader = new ShapeFileUtils();
//        ArrayList<ShapeModel> shapeModels = shapeReader.readShapeFile(filePath);
//        System.out.println(shapeModels);


    }
}
